#include <includes.h>
#include "cloud_aopu.h"

typedef struct vdata_config_param_t{
    uint8_t  sent;
    uint8_t  dev_addr;
    uint8_t  reg_type;
    uint16_t reg_addr;
    uint16_t reg_value;
    uint16_t reg_value_old;
    uint16_t tigger_greater;
    uint16_t tigger_equal;
    uint16_t tigger_less;
    struct vdata_config_param_t *prev;
    struct vdata_config_param_t *next;
}vdata_config_param_t;

const vdata_config_param_t config_param_default = {
    0,0,0,0,0,0,0,0,0,0,0
};

vdata_config_param_t my_config_param[3000];

vdata_config_param_t *vdata_config_param = 0;

vdata_config_param_t* vdata_config_param_add(uint8_t  dev_addr, uint8_t  reg_type, uint16_t reg_addr, uint16_t reg_value, uint16_t tigger_greater, uint16_t tigger_equal, uint16_t tigger_less)
{
    uint32_t min_addr = 0, max_addr = 0, input_addr = 0;
    vdata_config_param_t *node = vdata_config_param, *new_node = NULL;

    input_addr = ((uint32_t)dev_addr << 24) + ((uint32_t)reg_type << 16) + (uint32_t)reg_addr;
    while(node != NULL){
        min_addr = ((uint32_t)node->dev_addr << 24) + ((uint32_t)node->reg_type << 16) + (uint32_t)node->reg_addr;
        if(node->next){
            max_addr = ((uint32_t)node->next->dev_addr << 24) + ((uint32_t)node->next->reg_type << 16) + (uint32_t)node->next->reg_addr;
        }else{
            max_addr = 0xFFFFFFFF;
        }
        if((input_addr >= min_addr)&&(input_addr <= max_addr)){
            new_node = (vdata_config_param_t *)malloc(sizeof(vdata_config_param_t));
            memset(new_node, 0, sizeof(vdata_config_param_t));
            if(node->next){//如果之前存在下节点,[备注：先连接新节点再断开]
                new_node->next = node->next;//新节点连接下一个节点
                node->next->prev = new_node;//下下节点连接到新节点
            }
            new_node->dev_addr = dev_addr;
            new_node->reg_type = reg_type;
            new_node->reg_addr = reg_addr;
            new_node->reg_value = reg_value;
            new_node->tigger_greater = tigger_greater;
            new_node->tigger_equal = tigger_equal;
            new_node->tigger_less = tigger_less;

            new_node->prev = node;//新节点连接上一个节点
            node->next = new_node;//上节点连接到新节点
            return new_node;
        }
        node = node->next;
    }
    if(!node){
        vdata_config_param = (vdata_config_param_t *)malloc(sizeof(vdata_config_param_t));
        memset(vdata_config_param, 0, sizeof(vdata_config_param_t));
        vdata_config_param->prev = 0;
        vdata_config_param->next = 0;
        vdata_config_param->dev_addr = dev_addr;
        vdata_config_param->reg_type = reg_type;
        vdata_config_param->reg_addr = reg_addr;
        vdata_config_param->reg_value = reg_value;
        vdata_config_param->tigger_greater = tigger_greater;
        vdata_config_param->tigger_equal = tigger_equal;
        vdata_config_param->tigger_less = tigger_less;
    }
    return 0;
}

vdata_config_param_t* vdata_param_node_print(uint8_t  dev_addr, uint8_t  reg_type, uint16_t reg_addr)
{
    uint32_t node_addr = 0, input_addr = 0;
    vdata_config_param_t *node = vdata_config_param;

    input_addr = ((uint32_t)dev_addr << 24) + ((uint32_t)reg_type << 16) + (uint32_t)reg_addr;
    while(node != NULL){
        node_addr = ((uint32_t)node->dev_addr << 24) + ((uint32_t)node->reg_type << 16) + (uint32_t)node->reg_addr;
        if(input_addr == node_addr){
            printf("[%d][%d][%d][%d][%d][%d][%d]\r\n",
                   node->dev_addr,
                   node->reg_type,
                   node->reg_addr,
                   node->reg_value,
                   node->tigger_greater,
                   node->tigger_equal,
                   node->tigger_less);
            return node;
//            printf("->");
        }else{
//            printf("  ");
        }

//        printf("[%d][%d][%d][%d][%d][%d][%d]\r\n",
//               node->dev_addr,
//               node->reg_type,
//               node->reg_addr,
//               node->reg_value,
//               node->tigger_greater,
//               node->tigger_equal,
//               node->tigger_less);

        node = node->next;
    }
    return 0;
}

int vdata_config_param_delete(uint8_t  dev_addr, uint8_t  reg_type, uint16_t reg_addr)
{
    uint32_t node_addr = 0, input_addr = 0, node_deep = 0;
    vdata_config_param_t *node = vdata_config_param;

    input_addr = ((uint32_t)dev_addr << 24) + ((uint32_t)reg_type << 16) + (uint32_t)reg_addr;
    while(node != NULL){
        node_addr = ((uint32_t)node->dev_addr << 24) + ((uint32_t)node->reg_type << 16) + (uint32_t)node->reg_addr;
        if(node_addr == input_addr){
            if(node->next){//如果之前存在下节点
                node->next->prev = node->prev;//删除当前节点时，维护下一个节点的信息，
            }
            if(node->prev){//如果之前存在上节点
                node->prev->next = node->next;//删除当前节点时，维护上一个节点的信息
            }
            free(node);//释放资源
            node = NULL;
            return node_deep;
        }
        node_deep ++;
        node = node->next;
    }
    return 0;
}

int vdata_config_param_delete_all(void)
{
    uint32_t node_deep = 0;
    vdata_config_param_t *node = vdata_config_param, *free_node = NULL;

    while(node){
        free_node = node;
        free(free_node);
        node = node->next;
        node_deep ++;
    }
    return node_deep;
}

vdata_config_param_t* vdata_param_node_modify(uint8_t  dev_addr, uint8_t  reg_type, uint16_t reg_addr, uint16_t reg_value)
{
    uint32_t node_addr = 0, input_addr = 0;
    vdata_config_param_t *node = vdata_config_param;

    input_addr = ((uint32_t)dev_addr << 24) + ((uint32_t)reg_type << 16) + (uint32_t)reg_addr;
    while(node != NULL){
        node_addr = ((uint32_t)node->dev_addr << 24) + ((uint32_t)node->reg_type << 16) + (uint32_t)node->reg_addr;
        if(input_addr == node_addr){
            if(reg_value != node->reg_value){
                node->sent = 0;
                node->reg_value_old = node->reg_value;
                node->reg_value = reg_value;
            }
            return node;
        }
        node = node->next;
    }
    return 0;
}


int test(void)
{
    vdata_config_param_add(1, 1, 5, 5, 1, 2, 3);
    vdata_config_param_add(1, 1, 9, 9, 1, 2, 3);
    vdata_config_param_add(1, 1, 7, 7, 1, 2, 3);
    vdata_config_param_add(1, 1, 8, 8, 1, 2, 3);
    vdata_config_param_add(1, 1, 4, 4, 1, 2, 3);
    vdata_config_param_add(2, 3, 7, 7, 1, 2, 3);
    vdata_config_param_add(2, 3, 5, 5, 1, 2, 3);

    vdata_param_node_print(1, 1, 4);
    vdata_config_param_delete(1, 1, 4);
    vdata_param_node_print(1, 1, 4);
    vdata_param_node_print(1, 1, 7);
    vdata_param_node_print(2, 3, 5);
    return 1;
}


int vdata_csv_write(char *path)
 {
     FILE *fp = NULL; //需要注意
     fp = fopen(path, "a");
     if(NULL == fp)
     {
         return -1; //返回错误代码
     }
     char *a = "a";
     char *b = "b";
     char *c = "c";
       fprintf(fp, "%s,%s,%s\n", a, b, c);  //写入a,b,c到文件中

     fclose(fp);
     fp = NULL; //需要指向空，否则会指向原打开文件地址
     return 0;
 }

uint16_t vdata_mqtt_msg_id(void);
char *vdata_get_time_stamp(void);

int vdata_report_data_notif(vdata_mqtt_gateway_info_t *gateway, char *out)
{
    int count = 0;
    char *string = NULL, tagname[20];
    cJSON *send, *node_h, *node_b, *node_dl;
    vdata_config_param_t *node = NULL;

    gateway = gateway;
    send = cJSON_CreateObject();
    if(send){
        node_h = cJSON_CreateObject();
        if(!node_h){
            cJSON_Delete(send);
            return -1;
        }
        node_b = cJSON_CreateObject();
        if(!node_b){
            cJSON_Delete(send);
            cJSON_Delete(node_h);
            return -1;
        }
        node_dl = cJSON_CreateObject();
        if(!node_dl){
            cJSON_Delete(send);
            cJSON_Delete(node_h);
            cJSON_Delete(node_b);
            return -1;
        }

        cJSON_AddNumberToObject(node_h, "T",  5); //消息类型的十进制编码
        cJSON_AddNumberToObject(node_h, "ID", vdata_mqtt_msg_id());//消息流水号

        cJSON_AddNumberToObject(node_b, "rf", 5);
        cJSON_AddStringToObject(node_b, "ts", vdata_get_time_stamp());

        node = vdata_config_param;
        //"dl"
        while(node != NULL){
            if(node->sent){
                node = node->next;
                continue;
            }
            switch (node->reg_type) {
                case 1:
                    sprintf(tagname, "1X%d", node->reg_addr);
                    cJSON_AddItemToObject(node_dl, tagname, cJSON_CreateNumber(node->reg_value));
                    break;
                case 2:
                    sprintf(tagname, "2X%d", node->reg_addr);
                    cJSON_AddItemToObject(node_dl, tagname, cJSON_CreateNumber(node->reg_value));
                    break;
                case 3:
                    sprintf(tagname, "3X%d", node->reg_addr);
                    cJSON_AddItemToObject(node_dl, tagname, cJSON_CreateNumber(node->reg_value));
                    break;
                case 4:
                    sprintf(tagname, "4X%d", node->reg_addr);
                    cJSON_AddItemToObject(node_dl, tagname, cJSON_CreateNumber(node->reg_value));
                    break;
                default:
                    break;
            }
            node->sent = 1;
            node = node->next;
            if(++count > 50){
                break;
            }
        }

        cJSON_AddItemToObject(node_b, "dl", node_dl);
        cJSON_AddItemToObject(send, "h", node_h);
        cJSON_AddItemToObject(send, "b", node_b);

        string = cJSON_Print(send);
        cJSON_Minify(string);
        if(string){
            sprintf(out , "%s", string);
        }
        cJSON_Delete(send);
        free(string);
        if(node){
            return 1;
        }else{
            return 0;
        }
    }else{
        return -1;
    }
}

typedef struct vdata_modbus_cmd_t{
    uint8_t dev_addr;
    uint8_t reg_type;
    uint16_t reg_addr;
    uint16_t reg_num;
    struct vdata_modbus_cmd_t *next;
}vdata_modbus_cmd_t;

vdata_modbus_cmd_t *vdata_modbus_cmd_list;

int vdata_genarate_modbus_cmds(void)
{
    vdata_config_param_t *node = NULL;
    vdata_modbus_cmd_t vdata_modbus_cmd;
    uint16_t x1_max = 256, x2_max = 256, x3_max = 50, x4_max = 50;

    memset(&vdata_modbus_cmd, 0xFF, sizeof(vdata_modbus_cmd));
    node = vdata_config_param;
    if(node){
        vdata_modbus_cmd.dev_addr = node->dev_addr;
        vdata_modbus_cmd.reg_type = node->reg_type;
        vdata_modbus_cmd.reg_addr = node->reg_addr;
        vdata_modbus_cmd.reg_num = 1;
    }
    while(node != NULL){
        if(node->next){
            if((node->dev_addr != node->next->dev_addr)||
               (node->reg_type != node->next->reg_type)||
               ((node->reg_addr + 1) != node->next->reg_addr)){
                printf("[%d][%d][%d][%d]\r\n", vdata_modbus_cmd.dev_addr, vdata_modbus_cmd.reg_type, vdata_modbus_cmd.reg_addr, vdata_modbus_cmd.reg_num);
                vdata_modbus_cmd.dev_addr = node->next->dev_addr;
                vdata_modbus_cmd.reg_type = node->next->reg_type;
                vdata_modbus_cmd.reg_addr = node->next->reg_addr;
                vdata_modbus_cmd.reg_num = 1;
            }else{
                switch(vdata_modbus_cmd.reg_type){
                    case 1:
                        if(++vdata_modbus_cmd.reg_num >= x1_max){
                            printf("[%d][%d][%d][%d]\r\n", vdata_modbus_cmd.dev_addr, vdata_modbus_cmd.reg_type, vdata_modbus_cmd.reg_addr, vdata_modbus_cmd.reg_num);
                            vdata_modbus_cmd.dev_addr = node->dev_addr;
                            vdata_modbus_cmd.reg_type = node->reg_type;
                            vdata_modbus_cmd.reg_addr = node->reg_addr;
                            vdata_modbus_cmd.reg_num = 1;
                        }
                        break;

                    case 2:
                        if(++vdata_modbus_cmd.reg_num >= x2_max){
                            printf("[%d][%d][%d][%d]\r\n", vdata_modbus_cmd.dev_addr, vdata_modbus_cmd.reg_type, vdata_modbus_cmd.reg_addr, vdata_modbus_cmd.reg_num);
                            vdata_modbus_cmd.dev_addr = node->dev_addr;
                            vdata_modbus_cmd.reg_type = node->reg_type;
                            vdata_modbus_cmd.reg_addr = node->reg_addr;
                            vdata_modbus_cmd.reg_num = 1;
                        }
                        break;

                    case 3:
                        if(++vdata_modbus_cmd.reg_num >= x3_max){
                            printf("[%d][%d][%d][%d]\r\n", vdata_modbus_cmd.dev_addr, vdata_modbus_cmd.reg_type, vdata_modbus_cmd.reg_addr, vdata_modbus_cmd.reg_num);
                            vdata_modbus_cmd.dev_addr = node->dev_addr;
                            vdata_modbus_cmd.reg_type = node->reg_type;
                            vdata_modbus_cmd.reg_addr = node->reg_addr;
                            vdata_modbus_cmd.reg_num = 1;
                        }
                        break;

                    case 4:
                        if(++vdata_modbus_cmd.reg_num >= x4_max){
                            printf("[%d][%d][%d][%d]\r\n", vdata_modbus_cmd.dev_addr, vdata_modbus_cmd.reg_type, vdata_modbus_cmd.reg_addr, vdata_modbus_cmd.reg_num);
                            vdata_modbus_cmd.dev_addr = node->dev_addr;
                            vdata_modbus_cmd.reg_type = node->reg_type;
                            vdata_modbus_cmd.reg_addr = node->reg_addr;
                            vdata_modbus_cmd.reg_num = 1;
                        }
                        break;

                    default: break;
                }
            }
        }else{//最后一个
            printf("[%d][%d][%d][%d]\r\n", vdata_modbus_cmd.dev_addr, vdata_modbus_cmd.reg_type, vdata_modbus_cmd.reg_addr, vdata_modbus_cmd.reg_num);
            vdata_modbus_cmd.reg_num = 1;
        }
        node = node->next;
    }
    return 1;
}

int main(void)
{
    FILE *fp = NULL;
    char line[1000] = {0};
    char printf_buff[1024];
    int row = 0, col = 0, res = 0;
    vdata_config_param_t read_data = {0};
    vdata_mqtt_gateway_info_t gateway;

    printf("my_config_param size is -> %d\r\n", sizeof(my_config_param));
    fp = fopen("mb_conf.csv","at+");
    if(fp != NULL){
        char delims[] = ",";
        char *result = NULL;

        char *a;
        while (fgets(line, 100, fp)){
            a = line;
            col = 0;
            do{
                result = strtok( a, delims );
                a = NULL;
                switch(col){
                    case 0:break;
                    case 1:read_data.dev_addr = atoi(result);break;
                    case 2:read_data.reg_type = atoi(result);break;
                    case 3:read_data.reg_addr = atoi(result);break;
                    case 4:read_data.reg_value = atoi(result);break;
                    case 5:read_data.tigger_greater = atoi(result);break;
                    case 6:read_data.tigger_equal = atoi(result);break;
                    case 7:read_data.tigger_less = atoi(result);break;
                    default:break;
                }
                col ++;
            }while(result != NULL);
            if(row >= 1){
                vdata_config_param_add(
                            read_data.dev_addr,
                            read_data.reg_type,
                            read_data.reg_addr,
                            read_data.reg_value,
                            read_data.tigger_greater,
                            read_data.tigger_equal,
                            read_data.tigger_less);
            }
            row++;
        }
        vdata_param_node_print(1, 3, 209);
                do{
                    memset(printf_buff, 0, sizeof(printf_buff));
                    res = vdata_report_data_notif(&gateway, printf_buff);
                    printf("%s\r\n\r\n", printf_buff);
                }while(res != 0);

                vdata_param_node_modify(1, 3, 208, 55);

                do{
                    memset(printf_buff, 0, sizeof(printf_buff));
                    res = vdata_report_data_notif(&gateway, printf_buff);
                    printf("%s\r\n\r\n", printf_buff);
                }while(res != 0);
        vdata_genarate_modbus_cmds();
        fclose(fp);
        fp = NULL;
    }
}

